<!DOCTYPE html>
<html>
<head>
    <!-- 必须强制指定页面编码为 UTF-8 -->
    <meta charset="utf-8">

    <!-- Demo 的简要说明，必须要填写 -->
    <meta name="description" content="Kity 实现模拟光标输入">
    
    <!-- Demo 的作者，建议填写 -->
    <meta name="author" content="kity@baidu.com">
    
    <!-- Demo 的标题，必须填写 -->
    <title>模拟光标</title>
    
    <!-- Demo 开发过程中使用 CMD 引入 Kity 源码，方便调试 -->
    <!-- dev start -->
    <!-- 目录型的 Demo 注意修正源码引用路径 -->
    <script src="../dev-lib/sea.js"></script>
    <script>
        // 设置好 kity 源代码目录
        seajs.config( { base: '../src'} );
        // 定义 Demo 模块
        define('demo', function(require) { require('kity'); });
    </script>
    <script>
        // 启动 Demo 模块
        seajs.use('demo');
    </script>
    <!-- dev 版本 示例所需脚本文件 end -->

    <script src="public/jquery.js"></script>
    <style>
        .editor-container{

        }
        .receiver{
            position:absolute;
            padding:0;
            margin:0;
            word-wrap:break-word;
            clip:rect(1em 1em 1em 1em);

        }
    </style>
</head>
<body>
    <script>
        var Cursor = kity.createClass('Cursor',{
            base: kity.Line,
            constructor: function(height, color, width) {
                this.callBase();
                this.height = height || 20;
                this.stroke(color || 'blue',  width || 1);
                this.setHide();
                this.timer = null;
            },
            setPosition: function(offset) {
                try{
                    this.setPoint1(offset.x,offset.y);
                    this.setPoint2(offset.x,offset.y + this.height);
                }catch(e){
                    debugger
                }

                return this;
            },
            setHeight:function(height){
                this.height = height;
            },
            setHide:function(){
                clearInterval(this.timer);
                this.setStyle('display','none');
                return this;
            },
            setShowHold : function(){
                clearInterval(this.timer);
                this.setStyle('display','');
                return this;
            },
            setShow:function(){
                clearInterval(this.timer);
                var me = this,
                        state = '';
                this.timer = setInterval(function(){
                    me.setStyle('display',state);
                    state = state ? '' : 'none';
                },300);
                return this;
            },
            setTextShape:function(text){
                if(!text){
                    this.text = new kity.Text();
                }else{
                    this.text = text;
                }
                return this
            },
            getTextShape:function(){
                return this.text
            },
            setTxtContent : function(text){
                this.text.setContent(text)
            },
            updatePosition:function(index){

            }
        });
        var Receiver = kity.createClass('Receiver',{
            clear : function(){
                this.$container.html('');
                this.index = 0;
                return this;
            },
            constructor : function(){
                this.$container = $('<div contenteditable="true" class="receiver"></div>');
                this.$container.appendTo(document.body);
                this.$container.on('keydown keypress keyup', $.proxy(this.keyboardEvents,this));
                this.timer = null;
                this.index = 0;
            },
            setPosition : function(textShapeOffset){
                this.$container.css({
                    top:textShapeOffset.x,
                    left:textShapeOffset.y
                });
                this.textShape.setPosition(textShapeOffset.x, textShapeOffset.y);
                return this;
            },
            setRange : function(range,index){

                this.index = index || this.index;

                var text = this.$container[0].firstChild;
                console.log(text)
                console.log(this.index)
                range.setStart(text || this.$container[0], this.index).collapse(true);
                setTimeout(function(){
                    range.select()
                });
                return this;
            },
            setTextShape:function(textShape){
                if(!textShape){
                    textShape = new kity.Text();
                }
                this.textShape = textShape;
                return this;
            },
            setTextShapeSize:function(size){
                this.textShape.setSize(size);
                return this;
            },
            getTextShapeHeight:function(){
                return this.textShape.getRenderBox().height;
            },
            appendTextShapeToPaper:function(paper){
                paper.addShape(this.textShape);
                return this;
            },
            keyboardEvents : function(e){
                clearTimeout(this.timer);
                var me = this;
                switch(e.type){
                    case 'keyup':
                        this.textShape.setContent(this.$container.text().replace(/\u200b/g,''));
                        this.updateTextData();
                        this.updateCursor();
                        this.timer = setTimeout(function(){
                            me.cursor.setShow()
                        },500);
                        break;
                    case 'keypress':
                    case 'keyup':
                }
            },
            updateTextData : function(){
                this.textShape.textData =  this.getTextOffsetData();
                this.index = this.index + 1;
            },
            setCursor : function(cursor){
                this.cursor = cursor;
                return this;
            },
            updateCursor : function(){
                this.cursor.setShowHold();
                if(this.index == this.textData.length){

                    this.cursor.setPosition({
                        x : this.textData[this.index-1].x + this.textData[this.index-1].width,
                        y : this.textData[this.index-1].y
                    })
                }else if(this.index == 0){
                    this.cursor.setPosition({
                        x : this.textShape.getX(),
                        y : this.textData.getY()
                    })
                }else{
                    if(this.index + 1 == this.textData.length){
                        var lastChar = this.textData[this.index];
                        this.cursor.setPosition({
                            x : lastChar.x + lastChar.width,
                            y : lastChar.y
                        })
                    }else{
                        this.cursor.setPosition(this.textData[this.index])
                    }

                }
                return this;
            },
            getTextOffsetData:function(){
                var text = this.textShape.getContent();
                this.textData = [];
//                this.textShape.clearContent();

                for(var i= 0,l = text.length;i<l;i++){
                    var box = this.textShape.getExtentOfChar(i);
                    this.textData.push({
                        x:box.x,
                        y:box.y,
                        width:box.width,
                        height:box.height
                    })
                }


                return this;
            },
            setCurrentIndex:function(offset){
                var me = this;
                this.getTextOffsetData();
                var hadChanged = false;
                $.each(this.textData,function(i,v){
                    if(offset.x >= v.x && offset.x <= v.x + v.width){
                        if(offset.x  - v.x > v.width/2){
                            me.index = i + 1;

                        }else {
                            me.index = i

                        }
                        hadChanged = true;
                        return false;
                    }
                })
                return this;

            },
            setCursorHeight:function(){
                this.cursor.setHeight(this.getTextShapeHeight())
                return this;
            }
        });

        var Range = kity.createClass('Range',{
            constructor : function(){
                this.nativeRange = document.createRange();
                this.nativeSel = window.getSelection();
            },
            select:function(){
                var start = this.nativeRange.startContainer;
                if(start.nodeType == 1 && start.childNodes.length == 0){
                    var char = document.createTextNode('\u200b');
                    start.appendChild(char);
                    this.nativeRange.setStart(char,1);
                    this.nativeRange.collapse(true);
                }
                this.nativeSel.removeAllRanges();
                this.nativeSel.addRange(this.nativeRange);
                return this;
            },
            setStart:function(node,index){
                this.nativeRange.setStart(node,index);
                return this;
            },
            setEnd:function(node,index){
                this.nativeRange.setEnd(node,index);
                return this;
            },
            collapse:function(toStart){
                this.nativeRange.collapse(toStart === true);
                return this;
            },
            insertNode:function(node){
                this.nativeRange.insertNode(node);
                return this;
            }
        });

        var cursor = new Cursor();
        var receiver = new Receiver();
        var range = new Range();

        var paper = new kity.Paper(document.body).setHeight(500);
        paper.addShape(cursor)
            .setStyle('border','1px solid #ccc')
                .setStyle('cursor','text')
            .on('click',function(e){
                var originEvent = e.originEvent;
                var position = e.getPosition('top');
                if(e.targetShape.getType() != 'Text'){
                    var offset = e.getPosition('top');
                    cursor.setShow().setPosition(offset);
                    receiver.clear()
                            .setTextShape()
                            .setTextShapeSize(cursor.height)
                            .appendTextShapeToPaper(paper)
                            .setPosition(position)
                            .setRange(range,0)
                            .setCursor(cursor)
                }else{
                    receiver.setCursor(cursor)
                            .setTextShape(e.targetShape)
                            .setCursorHeight()
                            .setCurrentIndex(position)
                            .updateCursor()
                            .setRange(range)

                }


            })

    </script>
</body>
</html>